package com.springboot.seckill.controller;

import com.springboot.seckill.controller.dto.LoginDTO;
import com.springboot.seckill.controller.dto.RegisterDTO;
import com.springboot.seckill.controller.viewobject.UserVO;
import com.springboot.seckill.error.BusinessException;
import com.springboot.seckill.error.EmBusinessError;
import com.springboot.seckill.response.CommonReturnType;
import com.springboot.seckill.service.UserService;
import com.springboot.seckill.service.model.UserModel;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.util.DigestUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.Random;

/**
 * @Author: HuangDekai
 * @Date: 2022/3/7 18:00
 * @Version: 1.0
 * @since: jdk11
 */


@RestController("user")
@RequestMapping("/user")
    //DEFAULT_ALLOWED_HEADERS: 允许跨域传输所有的header参数, 将用于使用token放入header域, 做session共享的跨域请求
    //DEFAULT_ALLOW_CREDENTIALS = true: 需要配合前端设置xhrFields授信后使得跨域session共享
@CrossOrigin(allowCredentials = "true",  allowedHeaders = "*", originPatterns = "*")
public class UserController extends BaseController{

    @Autowired
    private UserService userService;
    @Autowired
    private HttpServletRequest httpServletRequest;

    @PostMapping(value = "/login", consumes = MediaType.APPLICATION_JSON_VALUE)
    public CommonReturnType login(@Validated @RequestBody LoginDTO loginDTO, BindingResult result) throws BusinessException {
        //入参校验
        if (result.hasErrors()) {
            throw new BusinessException(EmBusinessError.USER_LOGIN_FAIL, result.getFieldError().getDefaultMessage());
        }
        //用户登录服务, 用来校验用户登录是否合法
        UserModel userModel = userService.validateLogin(loginDTO.getTelphone(), this.encodeByMd5(loginDTO.getPassword()));

        //将登录凭证加入到用户登录成功的session内
        this.httpServletRequest.getSession().setAttribute("IS_LOGIN", true);
        this.httpServletRequest.getSession().setAttribute("LOGIN_USER", userModel);

        return CommonReturnType.create(null);
    }

    @PostMapping(value = "/register", consumes = MediaType.APPLICATION_JSON_VALUE)
    public CommonReturnType register(@Validated @RequestBody RegisterDTO registerDTO) throws BusinessException {
        // 验证手机号和对应的otpcode相符合
        String otpCode = (String) this.httpServletRequest.getSession().getAttribute(registerDTO.getTelphone());
        if (otpCode == null || !otpCode.equals(registerDTO.getOtpCode())) {
            throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR, "短信验证码不符合");
        }

        //用户注册流程
        UserModel userModel = convertFromRegisterDTO(registerDTO);
        userModel.setRegisterMode("byphone");
        userService.register(userModel);

        return CommonReturnType.create(null);
    }

    /**
     * 将RegisterDTO转换为UserModel
     * @param registerDTO RegisterDTO
     * @return UserModel
     */
    private UserModel convertFromRegisterDTO(RegisterDTO registerDTO) {
        if (registerDTO == null) {
            return null;
        }
        UserModel userModel = new UserModel();
        BeanUtils.copyProperties(registerDTO, userModel);
        userModel.setEncrptPassword(encodeByMd5(registerDTO.getPassword()));
        return userModel;
    }

    public String encodeByMd5(String str) {
        //确定计算方法
        return DigestUtils.md5DigestAsHex(str.getBytes());
    }

    /**
     * 用户获取otp短信接口
     * @param telphone 手机号
     * @return CommonReturnType
     */
    @PostMapping(value = "/getotp", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    public CommonReturnType getOtp(@RequestParam(name="telphone")String telphone) {
        //按照一定规则生成OTP验证码
        Random random = new Random();
        int randomInt = random.nextInt(89999);
        randomInt += 10000;
        String otpCode = String.valueOf(randomInt);

        //将OTP Code和对应用户的手机号关联 (一般Redis, 这里使用http session的方式绑定)
        httpServletRequest.getSession().setAttribute(telphone, otpCode);

        //将OTP验证码通过短信通道发送给用户 (省略)
        //敏感信息,实际项目中不应该打印(打印应该使用日志打印)
        System.out.println("telphone = "+telphone+" & otpCode = "+otpCode);

        return CommonReturnType.create(null);
    }

    /**
     * 获取用户
     * @param id 主键id
     * @return CommonReturnType
     * @throws BusinessException 用户不存在
     */
    @RequestMapping("/get")
    public CommonReturnType getUser(@RequestParam(name="id") Integer id) throws BusinessException {
        UserModel userModel = userService.getUserById(id);

        if (userModel == null) {
            throw new BusinessException(EmBusinessError.USER_NOT_EXIST);
        }

        UserVO userVO = convertFormatModel(userModel);

        return CommonReturnType.create(userVO);
    }

    /**
     * 将userModel转换为userVO
     * @param userModel UserModel
     * @return UserVO
     */
    private UserVO convertFormatModel(UserModel userModel) {
        if (userModel == null) {
            return null;
        }
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(userModel, userVO);
        return userVO;
    }



}
